// 102min used
#include "kernel/param.h"
#include "kernel/types.h"
#include "user/user.h"

#define BUFFER_BLOCK_SIZE 512

char *cp_str(const char *start, const char *end) {
  uint str_len = end - start;
  char *res = malloc((str_len + 1) * sizeof(char));

  memcpy(res, start, str_len);
  res[str_len] = '\0';

  return res;
}

void parseline(int argc, char *argv[], const char *p) {
  if (argc > MAXARG - 2) {
    fprintf(2, "xargs: too many parameters\n");
    exit(-1);
  }

  uint current_arg = argc;
  const char *q = p;

  for (; *p != '\0'; ++p) {
    if (*p == ' ') {
      argv[current_arg] = cp_str(q, p);

      while (*p == ' ') {
        ++p;
      }

      q = p;
      if (++current_arg >= MAXARG) {
        fprintf(2, "xargs: too many parameters\n");
        exit(-1);
      }
    }
  }

  argv[current_arg++] = cp_str(q, p);

  argv[current_arg] = 0;
}

void free_argv(char *argv[]) {
  for (char **p = argv; p; ++p) {
    free(p);
  }
  free(argv);
}

int main(int argc, char *argv[]) {
  char *buf = (char *)malloc(BUFFER_BLOCK_SIZE), *p = buf;

  while (read(0, p, 1) != 0) {
    if (*p == '\n') {
      if (fork()) {
        p = buf;
        int child_status;
        wait(&child_status);

      } else {

        *p = '\0';
        char **next_argv = (char **)malloc((MAXARG + 1) * sizeof(char *));
        for (int i = 1; i < argc; ++i) {
          next_argv[i - 1] = argv[i];
        }
        parseline(argc - 1, next_argv, buf);

        exec(next_argv[0], next_argv);
        fprintf(2, "xargs: failed to exec %s", next_argv[0]);
        break;
      }

    } else {
      ++p;
    }
  }

  free(buf);

  exit(0);
}
